<?php

/**
 * 基础模型
 */
class Model {

    /**
     * 表名
     * @var string 
     */
    protected $_table;

    /**
     * 主键ID字段名
     * @var int 
     */
    protected $_id = 'id';

    /**
     * 用户ID字段名
     * @var int 
     */
    protected $_uid = 'uid';

    /**
     * 排序字段名
     * @var string 
     */
    protected $_sort = 'sort';

    /**
     * 可填充字段数组和对应的数据类型
     * 
     * int、str、date、time、datetime、float
     * 
     * array('id' => 'int', 'title' => 'str', 'add_time' => 'datetime')
     * @var array 
     */
    protected $_fillable = null;

    /**
     * 用可填充字段过滤数据
     * @param array $data
     */
    protected function filter($data) {
        if ($this->_fillable && is_array($this->_fillable) && is_array($data)) {

            // 过滤不可填充字段
            $data = array_filter($data, function($k) {
                return array_key_exists($k, $this->_fillable);
            }, ARRAY_FILTER_USE_KEY);

            // 按字段数据类型处理数据
            array_walk($data, function(&$v, $k) {
                if ($this->_fillable[$k] == 'int') {
                    $v = intval($v);
                }
                if ($this->_fillable[$k] == 'float') {
                    $v = floatval($v);
                }
                if ($this->_fillable[$k] == 'str') {
                    $v = trim($v);
                }
                if ($this->_fillable[$k] == 'date') {
                    $v = Date::isDate($v) ? $v : null;
                }
                if ($this->_fillable[$k] == 'time') {
                    $v = Date::isTime($v) ? $v : null;
                }
                if ($this->_fillable[$k] == 'datetime') {
                    $v = Date::isDateTime($v) ? $v : null;
                }
            });
        }
        return $data;
    }

    public function add($data) {
        $data = $this->filter($data);
        $result = Db()->insert($this->_table, $data);
        if ($result) {
            return Db()->lastInsertId();
        }
        return false;
    }

    public function update($id, $data) {
        $data = $this->filter($data);
        $where = array($this->_id => $id);
        return Db()->update($this->_table, $data, $where);
    }

    public function updateByUid($uid, $data) {
        $data = $this->filter($data);
        $where = array($this->_uid => $uid);
        return Db()->update($this->_table, $data, $where);
    }

    public function updateInUid($id, $uid, $data) {
        $data = $this->filter($data);
        $where = array($this->_id => $id, $this->_uid => $uid);
        return Db()->update($this->_table, $data, $where);
    }

    public function remove($id) {
        $where = array($this->_id => $id);
        return Db()->delete($this->_table, $where);
    }

    public function removeByUid($uid) {
        $where = array($this->_uid => $uid);
        return Db()->delete($this->_table, $where);
    }

    public function removeInUid($id, $uid) {
        $where = array($this->_id => $id, $this->_uid => $uid);
        return Db()->delete($this->_table, $where);
    }

    public function get($id, $field = '') {
        $where = array($this->_id => $id);
        if ($field != '') {
            return Db()->getOne($this->_table)->fields($field)->where($where)->result();
        }
        return Db()->getRow($this->_table)->where($where)->result();
    }

    public function getc($id, $field = '', $expire = 10) {
        $name = 'record_' . $this->_table;
        $row = cache($name, $id);
        if (!$row) {
            $row = $this->get($id);
            cache($name, $id, $row, $expire);
        }
        if ($field != '') {
            return $row[$field];
        }
        return $row;
    }

    public function getByUid($uid, $field = '') {
        $where = array($this->_uid => $uid);
        if ($field != '') {
            return Db()->getOne($this->_table)->fields($field)->where($where)->result();
        }
        return Db()->getRow($this->_table)->where($where)->result();
    }

    public function getInUid($id, $uid, $field = '') {
        $where = array($this->_id => $id, $this->_uid => $uid);
        if ($field != '') {
            return Db()->getOne($this->_table)->fields($field)->where($where)->result();
        }
        return Db()->getRow($this->_table)->where($where)->result();
    }

    public function getAll($offset = null, $length = null, $filter = array(), $order = '') {
        $order || $order = "{$this->_id} desc";
        return Db()->getAll($this->_table)->where($filter)->limit($offset, $length)->order($order)->result();
    }

    public function exportAll($filter = array()) {
        return Db()->getAll($this->_table)->where($filter)->result();
    }

    public function countAll($filter = array()) {
        return Db()->count($this->_table)->where($filter)->result();
    }

    public function getListInUid($uid, $offset = null, $length = null, $filter = array(), $order = '') {
        $order || $order = "{$this->_id} desc";
        $filter[$this->_uid] = $uid;
        return Db()->getAll($this->_table)->where($filter)->order($order)->limit($offset, $length)->result();
    }

    public function countInUid($uid, $filter = array()) {
        $filter[$this->_uid] = $uid;
        return Db()->count($this->_table)->where($filter)->result();
    }

    public function setSort($id, $sort) {
        $data = array($this->_sort => $sort);
        $where = array($this->_id => $id);
        return Db()->update($this->_table, $data, $where);
    }
    
    public function setSortInUid($id, $uid, $sort) {
        $data = array($this->_sort => $sort);
        $where = array($this->_id => $id, $this->_uid => $uid);
        return Db()->update($this->_table, $data, $where);
    }

}
